<template>
  <el-dialog :model-value="modelValue" draggable @close="close()" :title="title" top="5vh">
    <el-input v-model="filterText" placeholder="请输入名称，按回车键【Enter】查询" />
    <el-scrollbar height="70vh">
      <el-tree ref="treeRef" :data="userMenuList" show-checkbox node-key="id" default-expand-all
        :expand-on-click-node="false" :check-on-click-node="true" :props="{
          children: 'children',
          label: 'name',
          disabled: 'isRoleMenu',
        }" :default-checked-keys="selectMenuIdList" :filter-node-method="filterNode" @check="handleCheck"
        :check-strictly="true">
        <template #default="{ node, data }">
          <span>
            <el-tag size="small" :type="data.menuType === MenuTypeEnum.Group
              ? 'success'
              : data.menuType === MenuTypeEnum.Menu
                ? 'danger'
                : data.menuType === MenuTypeEnum.List
                  ? 'warning'
                  : 'primary'
              ">
              {{ menuTypeFilter(data) }}
            </el-tag>
            <span>【{{ node.label }}】</span>
            <span v-if="data.isRoleMenu">【已通过角色分配】</span>
          </span>
        </template>
      </el-tree>
    </el-scrollbar>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="close()">取消</el-button>
        <el-button type="primary" @click="saveForm()" v-button="['api:sys:sysusermenu:create']">
          确认
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import UserMenuApi, { UserMenu, UserMenuCreate } from "@/api/sys/user/userMenu";
import EnumApi, { EnumData } from "@/api/enums";
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
import successMsg from "@/utils/successMsg";
import { RoleMenu } from "@/api/sys/role/roleMenu";

const treeRef = ref(ElTree);
const props = defineProps({
  modelValue: Boolean,
  info: Object,
  userId: String,
  title: String,
});

onMounted(async () => {
  await query();
  await getMenuTypeList();
});

const emits = defineEmits(["update:modelValue", "success"]);

const userMenuList = ref<UserMenu[]>([]);
const selectMenuIdList = ref([]);

const query = async () => {
  const { dataList, dataExt } = await UserMenuApi.query(props.userId);
  userMenuList.value = dataList;
  selectMenuIdList.value = dataExt;
};

const menuTypeList = ref<EnumData[]>([]);
const getMenuTypeList = async () => {
  menuTypeList.value = await EnumApi.QueryMenuTypeEnums();
};

const menuTypeFilter = computed(() => (item: UserMenu) => {
  return menuTypeList.value.find((x) => x.value === item.menuType)?.text;
});

const filterText = ref("");

watch(filterText, (val) => {
  treeRef.value!.filter(val);
});

const filterNode = (value: string, data: UserMenu) => {
  if (!value) return true;
  return data.name.includes(value);
};


// 点击节点复选框之后触发
const handleCheck = (checkedNode, checkedState) => {
  const { checkedKeys, halfCheckedKeys } = checkedState
  const isChecking = checkedKeys.includes(checkedNode.id)

  if (isChecking) {
    // 选中操作 - 处理父节点
    handleCheckOn(checkedNode, checkedKeys, halfCheckedKeys)
  } else {
    // 取消选中操作 - 处理父节点
    handleCheckOff(checkedNode, checkedKeys)
  }
}

// 处理选中操作
const handleCheckOn = (checkedNode, checkedKeys, halfCheckedKeys) => {
  const checkedNodeIds = getCheckedNodeIds();
  //选中父节点
  const parentNodes = getAllParentNodes(checkedNode);
  checkedNodeIds.push(...parentNodes);

  //选中子节点
  const childIds = [checkedNode.id];
  treeToList(childIds, checkedNode.children ?? []);

  checkedNodeIds.push(...childIds);
  treeRef.value.setCheckedKeys(checkedNodeIds);
}

// 处理取消选中操作
const handleCheckOff = (uncheckedNode, checkedKeys) => {
  const checkedNodeIds = getCheckedNodeIds();

  //移除子节点
  const childIds = [uncheckedNode.id];
  treeToList(childIds, uncheckedNode.children ?? []);

  let checkIds = checkedNodeIds.filter(x => !childIds.includes(x));

  //移除父节点
  const removeIds = [];
  const parentNodes = getAllParentNodes(uncheckedNode).reverse();
  parentNodes.forEach(id => {
    const node = treeRef.value.getNode(id);
    const childs = node.data.children.map(x => x.id);
    if (!checkIds.some(x => childs.includes(x))) {
      checkIds = checkIds.filter(x => x != id);
      removeIds.push(id);
    }
  });

  checkIds = checkIds.filter(x => !removeIds.includes(x));

  treeRef.value.setCheckedKeys(checkIds);
}


const treeToList = (menuIds: String[], menu: RoleMenu[]) => {
  menu.forEach((element) => {
    menuIds.push(element.id);
    if (element.children && element.children.length > 0) {
      treeToList(menuIds, element.children);
    }
  });
};

// 获取节点的所有父节点（从直接父节点到根节点）
const getAllParentNodes = (node) => {
  if (node.path) {
    return node.path.split(',');
  } else {
    return [];
  }
}

const getCheckedNodeIds = () => {
  return treeRef.value.getCheckedNodes(false, true).map((x) => x.id);
}

//提交数据
const userMenu = ref<UserMenuCreate>({
  userId: "",
  menuIdList: [],
});
const saveForm = async () => {
  userMenu.value.userId = props.userId;
  userMenu.value.menuIdList = treeRef.value.getCheckedNodes(false, true).map((x) => x.id);
  const { success, message } = await UserMenuApi.create(userMenu.value);
  successMsg(success, message, () => {
    emits("success");
    close();
  })
};

const close = () => {
  emits("update:modelValue");
};
</script>
